package org.dei.perla.sys.device.fpc;

import java.sql.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.TimeZone;

import org.dei.perla.parser.expressions.Constant;
import org.dei.perla.parser.expressions.ConstantBlob;
import org.dei.perla.parser.expressions.ConstantFloat;
import org.dei.perla.parser.expressions.ConstantID;
import org.dei.perla.parser.expressions.ConstantInteger;
import org.dei.perla.parser.expressions.ConstantString;
import org.dei.perla.parser.expressions.ConstantTimestamp;
import org.dei.perla.parser.expressions.OperationNotSupportedException;
import org.dei.perla.rockfall.utils.IntecDatabaseDump;
import org.dei.perla.sys.device.fpc.DSPICLog.datastructures.DevicesLog;
import org.dei.perla.sys.device.fpc.MPPT.datastructures.MpptData;
import org.dei.perla.sys.device.fpc.dspic.DSPicFPC;
import org.dei.perla.sys.device.fpc.dspic.datastructures.DspicDataBufferOnEvent;
import org.dei.perla.sys.device.fpc.dspic.datastructures.ED;
import org.dei.perla.sys.device.fpc.intec.IntecFpc;
import org.dei.perla.sys.llqruntime.datastructures.QueryRecordStructure;
import org.dei.perla.sys.llqruntime.datastructures.Record;
import org.dei.perla.utils.logger.SimpleLogger;

public class DBRecordUtil {
	
	public static ArrayList<Record> prepareEventRecords(DspicDataBufferOnEvent status, QueryRecordStructure onEventRecordStructure, int pDevNumber){
		if(status.getEventDataCount() == 0)
			return null;
		
		ED eventData;
		ArrayList<Record> arrayList = new ArrayList<Record>();
		for (int i = 0; i < status.getEventDataCount(); i ++) {
			// Inserisco i dati dell'accellerometro
			eventData = status.getEventData()[i];
			Record record = new Record(onEventRecordStructure);
			record.setField("ACQUISITION_TYPE", new ConstantInteger(DSPicFPC.ON_EVENT));
			record.setField("ID_NODO", new ConstantID(pDevNumber));
			record.setField("TIMESTAMP", new ConstantTimestamp(eventData.getTimestamp()));
			record.setField("FLAGS", new ConstantInteger(eventData.getFlags()));
			record.setField("SAMPLES", new ConstantInteger(eventData.getSamples()));
			record.setField("MAGNITUDEX", new ConstantInteger(eventData.getMagnitudeX()));
			record.setField("MAGNITUDEY", new ConstantInteger(eventData.getMagnitudeY()));
			record.setField("MAGNITUDEZ", new ConstantInteger(eventData.getMagnitudeZ()));
			record.setField("NOISEX", new ConstantInteger(eventData.getNoiseX()));
			record.setField("NOISEY", new ConstantInteger(eventData.getNoiseY()));
			record.setField("NOISEZ", new ConstantInteger(eventData.getNoiseZ()));
			record.setField("PEAKX", new ConstantInteger(eventData.getPeakX()));
			record.setField("PEAKY", new ConstantInteger(eventData.getPeakY()));
			record.setField("PEAKZ", new ConstantInteger(eventData.getPeakZ()));
			record.setField("DATA", new ConstantBlob(Arrays.copyOfRange(status.getEventDataSamples(), 2 * eventData.getStart(), 2 * eventData.getStop())));
			arrayList.add(record);
		}
		return arrayList;
	}

	public static Record prepareDevicesLogRecord(DevicesLog logData, QueryRecordStructure logRecordStructure, int pDevNumber){
		Record record = new Record(logRecordStructure);
		record.setField("TIMESTAMP", new ConstantTimestamp(logData.getTimestamp()));
		record.setField("NODE_ID", new ConstantInteger(logData.getNodeId()));
		record.setField("UPTIME", new ConstantInteger(logData.getUptime()));
		record.setField("DATA_TIMEOUT", new ConstantInteger(logData.getDataTimeout()));
		record.setField("PARAMETER_TIMEOUT", new ConstantInteger(logData.getParameterTimeout()));
		record.setField("ROUND", new ConstantInteger(logData.getRound()));
		return record;
	}
	
	public static Record prepareLowSamplingRateRecords(DspicDataBufferOnEvent status, QueryRecordStructure recordStructure, int pDevNumber){
		// Creo il record ed inserisco i dati a campionamento lento
		//java.util.Date date = new java.util.Date(System.currentTimeMillis());
		//DateFormat dfm = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
		//dfm.setTimeZone(TimeZone.getTimeZone("Europe/Rome"));
		Record record = new Record(recordStructure);
		//SimpleLogger.log(DBRecordUtil.class, dfm.format(date));
		long now = System.currentTimeMillis()*1000;
		record.setField("ACQUISITION_TYPE", new ConstantInteger(DSPicFPC.CONTINUOUS));
		record.setField("ID_NODO", new ConstantID(pDevNumber));
		record.setField("STATUS", new ConstantInteger(status.getStatus()));
		record.setField("TIMESTAMP", new ConstantTimestamp(status.getLowSamplingRateData().getTimestamp()));
		record.setField("TEMPERATURE", new ConstantInteger(status.getLowSamplingRateData().getTemperature()));
		record.setField("ATTITUDEX", new ConstantInteger(status.getLowSamplingRateData().getAttitudeX()));
		record.setField("ATTITUDEY", new ConstantInteger(status.getLowSamplingRateData().getAttitudeY()));
		record.setField("ATTITUDEZ", new ConstantInteger(status.getLowSamplingRateData().getAttitudeZ()));
		record.setField("CRACKMETER1", new ConstantInteger(status.getLowSamplingRateData().getCrackMeter1()));
		record.setField("CRACKMETER2", new ConstantInteger(status.getLowSamplingRateData().getCrackMeter2()));
		return record;
	}

	public static Record prepareMPPTDataRecords(FPC fpc, MpptData mpptData, QueryRecordStructure recordStructure, int pDevNumber) throws PerlaDataTransformException, OperationNotSupportedException{
		Record record = new Record(recordStructure);
		double pc, pv, pwr, bv;
		int freq;
		String status, overCharge;		
		
		Double[] coefficientPV = fpc.getCoefficients("panelVoltage");
		pc = PerlaDataTransform.linear(mpptData.getPanelCurrent(), fpc.getCoefficients("panelCurrent"));

		bv = PerlaDataTransform.linear(mpptData.getBatteryVoltage(), fpc.getCoefficients("batteryVoltage"));
		
		if((mpptData.getFlags() & 0x2) > 0){
			freq = 100000;
			pv = PerlaDataTransform.linear(mpptData.getPanelVoltage(), Arrays.copyOfRange(coefficientPV, 2, 4));
		}
		else{
			freq = 40000;
			pv = PerlaDataTransform.linear(mpptData.getPanelVoltage(), Arrays.copyOfRange(coefficientPV, 0, 2));
		}
		if((mpptData.getFlags() & 0x1) > 0){
			status = new String("Power ON");
		}
		else{
			status = new String("Power OFF");
			pc = 0.0;
			pv = 0.0;
		}
		
		if((mpptData.getFlags() & 0x4) > 0){
			overCharge = new String("overcharge ON");
		}
		else
			overCharge = new String("overcharge OFF");
		
		pwr = pc * bv;
			
		record.setField("MPPT_ID", new ConstantID(pDevNumber));
		record.setField("TIMESTAMP", new ConstantTimestamp(mpptData.getTimestamp()));
		record.setField("V_PANEL", new ConstantFloat(pv));
		record.setField("C_PANEL", new ConstantFloat(pc));
		record.setField("V_BATTERY", new ConstantFloat(bv));
		record.setField("POWER", new ConstantFloat(pwr));
		record.setField("FREQUENCY", new ConstantInteger(freq));
		record.setField("STATUS", new ConstantString(status));
		record.setField("OVERCHARGE", new ConstantString(overCharge));
		return record;
	}

	
	public static QueryRecordStructure createContinuousRecordStructure(){
		QueryRecordStructure continuousRecordStructure = new QueryRecordStructure();
		continuousRecordStructure.addFieldStructure("STATUS", ConstantInteger.class);
		continuousRecordStructure.addFieldStructure("ID_NODO", ConstantID.class);
		continuousRecordStructure.addFieldStructure("ACQUISITION_TYPE", ConstantInteger.class);
		continuousRecordStructure.addFieldStructure("TIMESTAMP", ConstantTimestamp.class);
		continuousRecordStructure.addFieldStructure("TEMPERATURE", ConstantInteger.class);
		continuousRecordStructure.addFieldStructure("ATTITUDEX", ConstantInteger.class);
		continuousRecordStructure.addFieldStructure("ATTITUDEY", ConstantInteger.class);
		continuousRecordStructure.addFieldStructure("ATTITUDEZ", ConstantInteger.class);
		continuousRecordStructure.addFieldStructure("CRACKMETER1", ConstantInteger.class);
		continuousRecordStructure.addFieldStructure("CRACKMETER2", ConstantInteger.class);
		return continuousRecordStructure;
	}

	public static QueryRecordStructure createDevicesLogRecordStructure(){
		QueryRecordStructure recordStructure = new QueryRecordStructure();
		recordStructure.addFieldStructure("TIMESTAMP", ConstantTimestamp.class);
		recordStructure.addFieldStructure("NODE_ID", ConstantInteger.class);
		recordStructure.addFieldStructure("UPTIME", ConstantInteger.class);
		recordStructure.addFieldStructure("OVERFLOW", ConstantInteger.class);
		recordStructure.addFieldStructure("DATA_TIMEOUT", ConstantInteger.class);
		recordStructure.addFieldStructure("PARAMETER_TIMEOUT", ConstantInteger.class);
		recordStructure.addFieldStructure("ROUND", ConstantInteger.class);
		return recordStructure;
	}
	
	public static QueryRecordStructure createMPPTDataRecordStructure(){
		QueryRecordStructure mpptDataRecordStructure = new QueryRecordStructure();
		mpptDataRecordStructure.addFieldStructure("MPPT_ID", ConstantID.class);
		mpptDataRecordStructure.addFieldStructure("TIMESTAMP", ConstantTimestamp.class);
		mpptDataRecordStructure.addFieldStructure("V_PANEL", ConstantFloat.class);
		mpptDataRecordStructure.addFieldStructure("C_PANEL", ConstantFloat.class);
		mpptDataRecordStructure.addFieldStructure("V_BATTERY", ConstantFloat.class);
		mpptDataRecordStructure.addFieldStructure("POWER", ConstantFloat.class);
		mpptDataRecordStructure.addFieldStructure("FREQUENCY", ConstantInteger.class);
		mpptDataRecordStructure.addFieldStructure("STATUS", ConstantString.class);
		mpptDataRecordStructure.addFieldStructure("OVERCHARGE", ConstantString.class);
		return mpptDataRecordStructure;
	}
	
	public static QueryRecordStructure createOnEventRecordStructure(){
		QueryRecordStructure onEventRecordStructure = new QueryRecordStructure();
		onEventRecordStructure.addFieldStructure("ID_NODO", ConstantID.class);
		onEventRecordStructure.addFieldStructure("ACQUISITION_TYPE", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("STATUS", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("NUM_EVENTS", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("FLAGS", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("SAMPLES", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("MAGNITUDEX", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("MAGNITUDEY", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("MAGNITUDEZ", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("PEAKX", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("PEAKY", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("PEAKZ", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("NOISEX", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("NOISEY", ConstantInteger.class);
		onEventRecordStructure.addFieldStructure("NOISEZ", ConstantInteger.class);
		
		onEventRecordStructure.addFieldStructure("DATA", ConstantBlob.class);
		onEventRecordStructure.addFieldStructure("TIMESTAMP", ConstantTimestamp.class);
		return onEventRecordStructure;
		
	}
	
	
}
